﻿/*
  Project: General Serializer
 * Developer: Tunisian
 * Publication date: 14 Junuary 2013
 */

//#define justforcompilation
using SerializeProject.Formatters;
#region namespace
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.Serialization;
using SerializeProject.Helpers;
using System.Diagnostics;
using System.IO.IsolatedStorage;
using System.Text;
#endregion

namespace SerializeProject
{
    /// <summary>
    /// This is the generic formatter that implements the I formatter
    /// </summary>
    public class GenericFormatter : IFormatter
    {
        #region class members

        public SerializationBinder Binder { get; set; }
        public StreamingContext Context { get; set; }
        public ISurrogateSelector SurrogateSelector { get; set; }

        /// <summary>
        /// The stream reader that reads data form file
        /// </summary>
        private StreamWriter streamWriter;
        /// <summary>
        /// The stream writer that writes data to file
        /// </summary>
        private StreamReader streamReader;
        /// <summary>
        /// The IFormat object that formats a graph to any kind of format
        /// developer shoud implement this intefrace to format the graph to 
        /// the desired format
        /// </summary>
        IFormat Format;
        /// <summary>
        /// Structure where information about storage are stored
        /// </summary>
        StorageModeStructure storageStructure;
        /// <summary>
        /// The format structures tells the generic formatter  about the
        /// IFomrat implementation going to be used to format the object
        /// or the graph of objects
        /// </summary>
        FormatStructure formatStructure;

        #endregion

        #region constructor


        /// <summary>
        /// Constructor: The reflexion is used to pass all the required information
        /// to the generic formatter instance going to be used to format the 
        /// graph of objects
        /// </summary>
        public GenericFormatter()
        {
            StackTrace stackTrace = new StackTrace();
            Type declaringType = stackTrace.GetFrame(1).GetMethod().DeclaringType;
            MemberInfo member = (from m in declaringType.GetMembers()
                                 where m.GetCustomAttributes<StorageModeAttribute>().Count() > 0
                                 select m).FirstOrDefault();
           StorageModeAttribute attr = (member.GetCustomAttributes<StorageModeAttribute>().ToArray())[0];
            storageStructure.Storage = attr.Storage;
            storageStructure.FileName = attr.FileName;
            storageStructure.Folder = attr.Folder;
            MemberInfo member2 = (from m in declaringType.GetMembers()
                                 where m.GetCustomAttributes<FormatAttribute>().Count() > 0
                                 select m).FirstOrDefault();
            string assembly = Assembly.GetExecutingAssembly().Location;
            //C:\Users\ROMO\documents\visual studio 2012\Projects\SerializeProject\SerializeProject\bin\Debug\SerializeProject.exe
            FormatAttribute attr2 = (member.GetCustomAttributes<FormatAttribute>().ToArray())[0];
            formatStructure.FormatClass = attr2.FormatType;

            Format = getIFormatHelper();
 
        }
        #endregion

        /// <summary>
        /// Deserializes an object
        /// </summary>
        /// <param name="serializationStream">The stream where the serialized object
        /// resides</param>
        /// <returns>Returns the serialized object</returns>
        public object Deserialize(System.IO.Stream serializationStream)
        {
            if (storageStructure.Storage == Storage.FileSystem)
            {
                try
                {
                    streamReader = new StreamReader(serializationStream);
                }
                catch (Exception caught)
                {
                    Trace.WriteLine(caught.Message);
                }
            }
            return DeserializationResult(serializationStream);
        }
        /// <summary>
        /// This method is called by the Deserilized method to deserialize the
        /// object
        /// </summary>
        /// <param name="serializationStream">The stream where the object resides</param>
        /// <returns>The deserialized object</returns>
        protected object DeserializationResult(System.IO.Stream serializationStream)
        {
            string fileContent; 
            switch(storageStructure.Storage)
            {
                case Storage.FileSystem:
                    {
                        using (streamReader)
                        {
                            fileContent = streamReader.ReadToEnd();
                            return buildGraph( fileContent);
                        }
                        
                    }
                case Storage.IsolatedStorageFile:
                        {
                            fileContent = readFromIsolatedStorageHelper(serializationStream,
                                storageStructure.Folder,
                                storageStructure.FileName,
                                storageStructure.Policy);
                            return buildGraph(fileContent);
                        }
                default:
                    {
                        return null;
                    }
            }
           
        }//End of deserialzationresult
        /// <summary>
        /// Method that  builds the node graph  from the object graph 
        /// </summary>
        /// <param name="fileContent">The string format of the serialized object</param>
        /// <returns>The serialized object</returns>
        private object buildGraph(string fileContent)
        {
            Node root = (Node)Format.stringToObject(fileContent);
            string assemblyName = Assembly.GetExecutingAssembly().FullName.AssemblyInf(AssemblyInformation.Name);
            Type t = Type.GetType(string.Format("{0}.{1}", assemblyName, root.Name));
            object mainObject = Activator.CreateInstance(t);
 
            if (mainObject.GetType().GetInterface("IEnumerable") == null)
            {
                IEnumerable<MemberInfo> fieldsAndPropertiesMain = getFiledsAndPropertiesHelper(mainObject);

                foreach (Node item in root.ChildNodes)
                {
                    MemberInfo currentmemberInfo = fieldsAndPropertiesMain.FirstOrDefault(x => x.Name.Equals(item.Name));
                    int memberIndex = 0;

                    if (item.IsComposedType == true)
                    {
                        t = Type.GetType(string.Format("{0}.{1}", assemblyName, item.Name));
                        string currentCompositeTypeName = item.Name;
                        object currentCompositeType = Activator.CreateInstance(t);
                        IEnumerable<MemberInfo> fieldsAndProperties = getFiledsAndPropertiesHelper(currentCompositeType);
                        var getCompositeTypeNodesQuery = from node in root.ChildNodes
                                                         join member in fieldsAndProperties on node.Name equals member.Name
                                                         select node;
                        foreach (MemberInfo memberInfo in fieldsAndProperties)
                        {
                            getCompositeTypeNodesQuery.GetEnumerator().MoveNext();
                            string value = (getCompositeTypeNodesQuery.ToArray())[memberIndex++].Value.ToString().Replace('"', ' ');
                            bool propertyIsSet = setValueHelper(currentCompositeType, value, memberInfo);

                        }
                        //start here 
                        mainObject.GetType().GetProperty(currentCompositeTypeName).SetValue(mainObject, currentCompositeType);
                    }
                    else if (item.IsComposedType == false)
                    {
                        bool peopertyIsSet = setValueHelper(mainObject, item.Value.ToString(), currentmemberInfo);
                    }

                }
                
            }
          //TO DO implement this to serilize collections and lists
            else if (mainObject.GetType().GetInterface("IEnumerable") != null)
            {
                
                Type genericArgument = mainObject.GetType().GetGenericArguments()[0];
                    if (genericArgument!=null)
                    {

                        throw new NotImplementedException("Should be implemented to" + 
                        "support the list objects serialization");
                        
                        /*if (genericArgument.IsValueType || genericArgument.Equals(typeof(string)))
                        {

                           
                        }
                        else if (genericArgument.IsClass || genericArgument.IsInterface)
                        {

                        } */
                    }
                    else
                    {
                        foreach (var item in root.ChildNodes)
                        {
                             
                        }
                    }
            }
            return mainObject;
        }//end of build graph
        /// <summary>
        /// Method: Serialize an object to a stream
        /// </summary>
        /// <param name="serializationStream">The stream where the object will resides</param>
        /// <param name="graph">The object going to be serialized</param>
        public void Serialize(System.IO.Stream serializationStream, object graph)
        {
             streamWriter = new StreamWriter(serializationStream);
             SerializationResult(serializationStream, graph);
        } 
        /// <summary>
        /// Method: The method to whom the seralize method delegates the job
        /// </summary>
        /// <param name="serializationStream"></param>
        /// <param name="graph"></param>
        protected void SerializationResult(System.IO.Stream serializationStream, object graph)
        {
            if (graph.GetType().GetCustomAttribute(typeof(SerializableAttribute)) != null)
            {
                Node root = new Node
                { 
                    Name = graph.GetType().Name, 
                    Value = graph,
                    IsComposedType=true,
                    IsRoot=true 
                };
                root.setChildNodes();
                parseGraph(graph,root);
                string result = Format.objectTostring(root);
                switch (storageStructure.Storage)
                {
                    case Storage.FileSystem:
                        {
                            using (streamWriter)
                            {
                                streamWriter.Write(result);
                                streamWriter.Flush();
                                break;
                            }
                           
                        }
                    case Storage.IsolatedStorageFile:
                        {
                                bool isSerialized = writeToInIsolatedStorageHelper(serializationStream,
                                storageStructure.Folder,
                                storageStructure.FileName,
                                result, null);
                            break;
                        }
                    
                    default:
                        break;
                }

               
            }
            else
            {
                string message = "This class is  not marked as serializable, " +
                    "it should be decorated by the SerializableAttribute";
                throw new SerializationException(message);
            }
        }//end of serialization result

        /// <summary>
        /// Method: it parses the object graph to node graph
        /// </summary>
        /// <param name="graph"></param>
        /// <param name="node"></param>
        private void parseGraph(object graph,Node node)
        {
           if (graph.GetType().GetInterface("IEnumerable") != null)
            {
                node.IsIEnumerable = true;
                IEnumerable list = graph as IEnumerable;
                node.setChildNodes();
                foreach (var element in list)
                {           
                    node.addChildNode(new Node { Value = element });
                }
            }
            else
            {
                var fieldOrPropertyQuery = getFiledsAndPropertiesHelper(graph);
                foreach (var item in fieldOrPropertyQuery)
                {

                    if (item is PropertyInfo)
                    {
                        #region propertyInfo
                        PropertyInfo prop = item as PropertyInfo;
                        object value = prop.GetValue(graph);
                        Node current = new Node
                        {
                            Name = prop.Name,
                            Value = value
                        };
                        if (prop.PropertyType.IsValueType || prop.PropertyType.Equals(typeof(string)))
                        {
                            node.addChildNode(current);
                        }
                        else if (prop.PropertyType.IsClass || prop.PropertyType.IsInterface)
                        {
                            current.IsComposedType = true;
                            if (prop.PropertyType.GetInterface("IEnumerable") != null)
                            {
                                IEnumerable list = prop.GetValue(graph) as IEnumerable;
                                current.setChildNodes();
                                foreach (var element in list)
                                {               
                                    current.addChildNode(new Node { Value = element });
                                }
                            }
                            current.setChildNodes();
                            node.addChildNode(current);
                            parseGraph(value, current);
                        }

                        #endregion
                    }
                    else if (item is FieldInfo)
                    {
                        #region fieldInfo
                        FieldInfo field = item as FieldInfo;
                        object value = field.GetValue(graph);
                        Node current = new Node
                        {
                            Name = field.Name,
                            Value = value
                        };
                        if (field.FieldType.IsValueType || field.FieldType.Equals(typeof(string)))
                        {
                            node.addChildNode(current);
                        }
                        else if (field.FieldType.IsClass || field.FieldType.IsInterface)
                        {
                            current.IsComposedType = true;
                            if (field.FieldType.GetInterface("IEnumerable") != null)
                            {
                                IEnumerable list = field.GetValue(graph) as IEnumerable;
                                current.setChildNodes();
                                foreach (var element in list)
                                {             
                                    current.addChildNode(new Node { Value = element });
                                }
                            }
                            current.setChildNodes();
                            node.addChildNode(current);
                            parseGraph(value, current);
                        }

                        #endregion
                    }

                  }
            }
            
        }//end of parseGraph

        #region helpers
        /// <summary>
        /// Method: it helps instanciate the required IFormat object 
        /// form the information got from the attribute that decorates the 
        /// generic formatter take a look on the main program to check that
        /// </summary>
        /// <returns>returns IFormatter objects</returns>
        private IFormat getIFormatHelper()
        {
            Assembly ass = Assembly.GetExecutingAssembly();
            Type typeOfFormat = ass.GetType(formatStructure.FormatClass.FullName);
            object constructedInstance = Activator.CreateInstance(typeOfFormat);
            return (IFormat)constructedInstance;
        }
        /// <summary>
        /// Method: it helps parse an object and returns a set of 
        /// fieleds and properties of a given object
        /// </summary>
        /// <param name="graph">it is the object going to be serialized</param>
        /// <returns>A collection of MemberInfo of the parsed object</returns>
        private static IEnumerable<MemberInfo> getFiledsAndPropertiesHelper(object graph)
        {
            MemberInfo[] members = graph.GetType().GetMembers();
            
            var fieldOrPropertyQuery = from element in members
                                       where
                                       ((element is FieldInfo || element is PropertyInfo))
                                       select element;
            return fieldOrPropertyQuery;
        }
        /// <summary>
        /// Method: This method is invoked when the generic formatter user chooses
        /// the isolated storage as storage mode 
        /// </summary>
        /// <param name="isolatedStorageFilestream">The stream where the 
        /// object is going to be stored</param>
        /// <param name="directoryname">The name of the folder where the 
        /// file containing the serialized object is going to be stored</param>
        /// <param name="filename">The name of the file where the 
        /// object is going to be stored</param>
        /// <param name="policyType">The type of the used policy when it is the case
        /// of restricted permissions and security configuration case</param>
        /// <returns>returns the string that contains the serialized object</returns>
        private static string readFromIsolatedStorageHelper(Stream isolatedStorageFilestream,
           string directoryname, string filename, Type policyType)
        {
            IsolatedStorageFile isf = IsolatedStorageFile.GetStore(IsolatedStorageScope.User |
            IsolatedStorageScope.Assembly | IsolatedStorageScope.Domain,
                  policyType,
                  policyType);
            isolatedStorageFilestream = new IsolatedStorageFileStream(Path.Combine(directoryname, filename),
                FileMode.Open,
                isf);
            StreamReader reader = new StreamReader(isolatedStorageFilestream);
            string str = reader.ReadToEnd();
            return str;
        }
        /// <summary>
        /// Method: It is used to write to the isolated storage file
        /// </summary>
        /// <param name="isolatedStorageFilestream">The stream where the 
        /// object is stored</param>
        /// <param name="directoryname">The name of the folder where the 
        /// file containing the serialized object is stored</param>
        /// <param name="filename">The name of the file where the 
        /// object is  stored</param>
        /// <param name="objectFormat">The obejct format to be parsed </param>
        /// <param name="policyType">The policy type where there is security permission issues</param>
        /// <returns></returns>
        private static bool writeToInIsolatedStorageHelper(Stream isolatedStorageFilestream,
            string directoryname, string filename,string objectFormat, Type policyType)
        {
            try
            {
                IsolatedStorageFile isf = IsolatedStorageFile.GetStore(IsolatedStorageScope.User |
                    IsolatedStorageScope.Assembly | IsolatedStorageScope.Domain,
                          policyType,
                          policyType);
                isolatedStorageFilestream = new IsolatedStorageFileStream(Path.Combine(directoryname, filename),
                    FileMode.Create,
                    isf);
                byte[] data = Encoding.GetEncoding("utf-8").GetBytes(objectFormat);
                isolatedStorageFilestream.Write(data, 0, data.Length);
                isolatedStorageFilestream.Close();
                return true;
            }
            catch (ApplicationException caught)
            {
                Trace.Write(string.Format("Message: {0}, Source: {1}",
                    caught.Message,
                    caught.Source));
                return false;
            }
        }  
 
        /// <summary>
        /// Method: This is form string to other types converter 
        /// </summary>
        /// <param name="mainObject">The object containing the member property/field</param>
        /// <param name="value">The value going to be converted</param>
        /// <param name="memberInfo">The memberinfo that tells about that member</param>
        /// <returns>boolean that indicates wheter the value is successfully translated</returns>
        private static bool setValueHelper(object mainObject, string value, MemberInfo memberInfo)
        {
            PropertyInfo prop = default(PropertyInfo);
            FieldInfo field = default(FieldInfo);
            if (memberInfo is PropertyInfo)
            {
                #region  propertyinfo
                prop = memberInfo as PropertyInfo;
                if (prop.PropertyType.Equals(typeof(bool)))
                {
                    bool finalValue;
                    bool flag = bool.TryParse(value, out finalValue);
                    prop.SetValue(mainObject, finalValue);
                    return true;
                }
                else if (prop.PropertyType.Equals(typeof(byte)))
                {
                    byte finalValue;
                    bool flag = byte.TryParse(value, out finalValue);
                    prop.SetValue(mainObject, finalValue);
                    return true;
                }
                else if (prop.PropertyType.Equals(typeof(char)))
                {
                    char finalValue;
                    bool flag = char.TryParse(value, out finalValue);
                    prop.SetValue(mainObject, finalValue);
                    return true;
                }
                else if (prop.PropertyType.Equals(typeof(decimal)))
                {
                    decimal finalValue;
                    bool flag = decimal.TryParse(value, out finalValue);
                    prop.SetValue(mainObject, finalValue);
                    return true;
                }
                else if (prop.PropertyType.Equals(typeof(double)))
                {
                    double finalValue;
                    bool flag = double.TryParse(value, out finalValue);
                    prop.SetValue(mainObject, finalValue);
                    return true;
                }
                else if (prop.PropertyType.Equals(typeof(float)))
                {
                    float finalValue;
                    bool flag = float.TryParse(value, out finalValue);
                    prop.SetValue(mainObject, finalValue);
                    return true;
                }
                else if (prop.PropertyType.Equals(typeof(int)))
                {
                    int finalValue;
                    bool flag = int.TryParse(value, out finalValue);
                    prop.SetValue(mainObject, finalValue);
                    return true;
                }
                else if (prop.PropertyType.Equals(typeof(long)))
                {
                    long finalValue;
                    bool flag = long.TryParse(value, out finalValue);
                    prop.SetValue(mainObject, finalValue);
                    return true;
                }
                else if (prop.PropertyType.Equals(typeof(sbyte)))
                {
                    sbyte finalValue;
                    bool flag = sbyte.TryParse(value, out finalValue);
                    prop.SetValue(mainObject, finalValue);
                    return true;
                }
                else if (prop.PropertyType.Equals(typeof(short)))
                {
                    short finalValue;
                    bool flag = short.TryParse(value, out finalValue);
                    prop.SetValue(mainObject, finalValue);
                    return true;
                }
                else if (prop.PropertyType.Equals(typeof(uint)))
                {
                    short finalValue;
                    bool flag = short.TryParse(value, out finalValue);
                    prop.SetValue(mainObject, finalValue);
                    return true;
                }
                else if (prop.PropertyType.Equals(typeof(ulong)))
                {
                    ulong finalValue;
                    bool flag = ulong.TryParse(value, out finalValue);
                    prop.SetValue(mainObject, finalValue);
                    return true;
                }
                else if (prop.PropertyType.Equals(typeof(ushort)))
                {
                    ushort finalValue;
                    bool flag = ushort.TryParse(value, out finalValue);
                    prop.SetValue(mainObject, finalValue);
                    return true;
                }
                else if (prop.PropertyType.Equals(typeof(string)))
                {
                    prop.SetValue(mainObject, value);
                    return true;
                }
                //Will be verified later
                else if (prop.PropertyType.GetInterface("IEnumerable") != null)
                {
                    prop.SetValue(mainObject, value);
                    return true;
                }
                else if (prop.PropertyType.IsArray)
                {
                    prop.SetValue(mainObject, value);
                    return true;
                }
                else if(prop.PropertyType.IsEnum)
                {
                    Type t = prop.PropertyType;
                    FieldInfo enumMember = (t.GetMember(value))[0] as FieldInfo ;
                    object enumMemberValue = enumMember.GetValue(enumMember);
                    prop.SetValue(mainObject, enumMemberValue);
                    return true;
                }
                if (prop.PropertyType.Equals(typeof(bool?)))
                {
                    bool boolValue;
                    bool? finalValue = bool.TryParse(value, out boolValue) ? (bool?)boolValue : null;
                    prop.SetValue(mainObject, finalValue);
                    return true;
                }
                else if (prop.PropertyType.Equals(typeof(byte?)))
                {
                    byte byteValue;
                    byte? finalValue = byte.TryParse(value, out byteValue) ? (byte?)byteValue : null;
                    prop.SetValue(mainObject, finalValue);
                    return true;
                }
                else if (prop.PropertyType.Equals(typeof(char?)))
                {
                    char charValue;
                    char? finalValue = char.TryParse(value, out charValue) ? (char?)charValue : null;
                    prop.SetValue(mainObject, finalValue);
                    return true;
                }
                else if (prop.PropertyType.Equals(typeof(decimal?)))
                {
                    decimal decimalValue;
                    decimal? finalValue = decimal.TryParse(value, out decimalValue) ? (decimal?)decimalValue : null;
                    prop.SetValue(mainObject, finalValue);
                    return true;
                }
                else if (prop.PropertyType.Equals(typeof(double?)))
                {
                    double doubleValue;
                    double? finalValue = double.TryParse(value, out doubleValue) ? (double?)doubleValue : null;
                    prop.SetValue(mainObject, doubleValue);
                    return true;
                }
                else if (prop.PropertyType.Equals(typeof(float?)))
                {
                    float floatValue;
                    float? finalValue = float.TryParse(value, out floatValue) ? (float?)floatValue : null;
                    prop.SetValue(mainObject, finalValue);
                    return true;
                }
                else if (prop.PropertyType.Equals(typeof(int?)))
                {
                    int intValue;
                    int? finalValue = int.TryParse(value, out intValue) ? (int?)intValue : null;
                    prop.SetValue(mainObject, finalValue);
                    return true;
                }
                else if (prop.PropertyType.Equals(typeof(long?)))
                {
                    long longValue;
                    long? finalValue = long.TryParse(value, out longValue) ? (long?)longValue : null;
                    prop.SetValue(mainObject, finalValue);
                    return true;
                }
                else if (prop.PropertyType.Equals(typeof(sbyte?)))
                {
                    sbyte sbyteValue;
                    sbyte? finalValue = sbyte.TryParse(value, out sbyteValue) ? (sbyte?)sbyteValue : null;
                    prop.SetValue(mainObject, finalValue);
                    return true;
                }
                else if (prop.PropertyType.Equals(typeof(short?)))
                {
                    short shortValue;
                    short? finalValue = short.TryParse(value, out shortValue) ? (short?)shortValue : null;
                    prop.SetValue(mainObject, finalValue);
                    return true;
                }
                else if (prop.PropertyType.Equals(typeof(uint?)))
                {
                    uint uintValue;
                    uint? finalValue = uint.TryParse(value, out uintValue) ? (uint?)uintValue : null;
                    prop.SetValue(mainObject, finalValue);
                    return true;
                }
                else if (prop.PropertyType.Equals(typeof(ulong?)))
                {
                    ulong ulongValue;
                    ulong? finalValue = ulong.TryParse(value, out ulongValue) ? (ulong?)ulongValue : null;
                    prop.SetValue(mainObject, finalValue);
                    return true;
                }
                else if (prop.PropertyType.Equals(typeof(ushort?)))
                {
                    ushort ushortValue;
                    ushort? finalValue = ushort.TryParse(value, out ushortValue) ? (ushort?)ushortValue : null;
                    prop.SetValue(mainObject, finalValue);
                    return true;
                }
                #endregion
                
            }
            else if (memberInfo is FieldInfo)
            {
                #region fieldinfo
                field = memberInfo as FieldInfo;
                if (field.FieldType.Equals(typeof(bool)))
                {
                    bool finalValue;
                    bool flag = bool.TryParse(value, out finalValue);
                    prop.SetValue(mainObject, finalValue);
                    return true;
                }
                else if (field.FieldType.Equals(typeof(byte)))
                {
                    byte finalValue;
                    bool flag = byte.TryParse(value, out finalValue);
                    field.SetValue(mainObject, finalValue);
                    return true;
                }
                else if (field.FieldType.Equals(typeof(char)))
                {
                    char finalValue;
                    bool flag = char.TryParse(value, out finalValue);
                    field.SetValue(mainObject, finalValue);
                    return true;
                }
                else if (field.FieldType.Equals(typeof(decimal)))
                {
                    decimal finalValue;
                    bool flag = decimal.TryParse(value, out finalValue);
                    field.SetValue(mainObject, finalValue);
                    return true;
                }
                else if (field.FieldType.Equals(typeof(double)))
                {
                    double finalValue;
                    bool flag = double.TryParse(value, out finalValue);
                    field.SetValue(mainObject, finalValue);
                    return true;
                }
                else if (field.FieldType.Equals(typeof(float)))
                {
                    float finalValue;
                    bool flag = float.TryParse(value, out finalValue);
                    field.SetValue(mainObject, finalValue);
                    return true;
                }
                else if (field.FieldType.Equals(typeof(int)))
                {
                    int finalValue;
                    bool flag = int.TryParse(value, out finalValue);
                    field.SetValue(mainObject, finalValue);
                    return true;
                }
                else if (field.FieldType.Equals(typeof(long)))
                {
                    long finalValue;
                    bool flag = long.TryParse(value, out finalValue);
                    field.SetValue(mainObject, finalValue);
                    return true;
                }
                else if (field.FieldType.Equals(typeof(sbyte)))
                {
                    sbyte finalValue;
                    bool flag = sbyte.TryParse(value, out finalValue);
                    field.SetValue(mainObject, finalValue);
                    return true;
                }
                else if (field.FieldType.Equals(typeof(short)))
                {
                    short finalValue;
                    bool flag = short.TryParse(value, out finalValue);
                    field.SetValue(mainObject, finalValue);
                    return true;
                }
                else if (field.FieldType.Equals(typeof(uint)))
                {
                    short finalValue;
                    bool flag = short.TryParse(value, out finalValue);
                    field.SetValue(mainObject, finalValue);
                    return true;
                }
                else if (field.FieldType.Equals(typeof(ulong)))
                {
                    ulong finalValue;
                    bool flag = ulong.TryParse(value, out finalValue);
                    field.SetValue(mainObject, finalValue);
                    return true;
                }
                else if (field.FieldType.Equals(typeof(ushort)))
                {
                    ushort finalValue;
                    bool flag = ushort.TryParse(value, out finalValue);
                    field.SetValue(mainObject, finalValue);
                    return true;
                }
                else if (field.FieldType.Equals(typeof(string)))
                {
                    field.SetValue(mainObject, value);
                    return true;
                }
                if (field.FieldType.Equals(typeof(bool?)))
                {
                    bool boolValue;
                    bool? finalValue = bool.TryParse(value, out boolValue) ? (bool?)boolValue : null;
                    field.SetValue(mainObject, finalValue);
                    return true;
                }
                else if (field.FieldType.Equals(typeof(byte?)))
                {
                    byte byteValue;
                    byte? finalValue = byte.TryParse(value, out byteValue) ? (byte?)byteValue : null;
                    field.SetValue(mainObject, finalValue);
                    return true;
                }
                else if (field.FieldType.Equals(typeof(char?)))
                {
                    char charValue;
                    char? finalValue = char.TryParse(value, out charValue) ? (char?)charValue : null;
                    field.SetValue(mainObject, finalValue);
                    return true;
                }
                else if (field.FieldType.Equals(typeof(decimal?)))
                {
                    decimal decimalValue;
                    decimal? finalValue = decimal.TryParse(value, out decimalValue) ? (decimal?)decimalValue : null;
                    field.SetValue(mainObject, finalValue);
                    return true;
                }
                else if (field.FieldType.Equals(typeof(double?)))
                {
                    double doubleValue;
                    double? finalValue = double.TryParse(value, out doubleValue) ? (double?)doubleValue : null;
                    field.SetValue(mainObject, finalValue);
                    return true;
                }
                else if (field.FieldType.Equals(typeof(float?)))
                {
                    float floatValue;
                    float? finalValue = float.TryParse(value, out floatValue) ? (float?)floatValue : null;
                    field.SetValue(mainObject, finalValue);
                    return true;
                }
                else if (field.FieldType.Equals(typeof(int?)))
                {
                    int intValue;
                    int? finalValue = int.TryParse(value, out intValue) ? (int?)intValue : null;
                    field.SetValue(mainObject, finalValue);
                    return true;
                }
                else if (field.FieldType.Equals(typeof(long?)))
                {
                    long longValue;
                    long? finalValue = long.TryParse(value, out longValue) ? (long?)longValue : null;
                    field.SetValue(mainObject, finalValue);
                    return true;
                }
                else if (field.FieldType.Equals(typeof(sbyte?)))
                {
                    sbyte sbyteValue;
                    sbyte? finalValue = sbyte.TryParse(value, out sbyteValue) ? (sbyte?)sbyteValue : null;
                    field.SetValue(mainObject, finalValue);
                    return true;
                }
                else if (field.FieldType.Equals(typeof(short?)))
                {
                    short shortValue;
                    short? finalValue = short.TryParse(value, out shortValue) ? (short?)shortValue : null;
                    field.SetValue(mainObject, finalValue);
                    return true;
                }
                else if (field.FieldType.Equals(typeof(uint?)))
                {
                    uint uintValue;
                    uint? finalValue = uint.TryParse(value, out uintValue) ? (uint?)uintValue : null;
                    field.SetValue(mainObject, finalValue);
                    return true;
                }
                else if (field.FieldType.Equals(typeof(ulong?)))
                {
                    ulong ulongValue;
                    ulong? finalValue = ulong.TryParse(value, out ulongValue) ? (ulong?)ulongValue : null;
                    field.SetValue(mainObject, finalValue);
                    return true;
                }
                else if (field.FieldType.Equals(typeof(ushort?)))
                {
                    ushort ushortValue;
                    ushort? finalValue = ushort.TryParse(value, out ushortValue) ? (ushort?)ushortValue : null;
                    field.SetValue(mainObject, finalValue);
                    return true;
                }
                #endregion
            }
            return false;
        }
        #endregion

#if alt1
        
        private void parseGraph(object graph)
        {
            if (graph!=null)
            {
        #region IEnumerable case
                if (graph.GetType().GetInterface("IEnumerable")!=null)
                {
                    int index2 = 0;
                    //Mor on this later
                    Node node = new Node { CurrentMember = graph.GetType() };
                    foreach (var item in (IEnumerable)graph)
                    {
                        nodeSchedule.Add(index2++,node);
                        parseGraph(item);
                    }
                }
        #endregion
                else
                {
                    PropertyInfo prop = default(PropertyInfo);
                    FieldInfo field =default(FieldInfo);
                    Node node;
                    MemberInfo[] members = graph.GetType().GetMembers();
                    foreach (var item in members)
                    {
                        if (item is FieldInfo)
                        {
                            field = item as FieldInfo;
                            if ((field.FieldType.IsValueType || field.FieldType.Equals(typeof(string))))
                            {
                                
                                node = new Node { CurrentMember = prop, ParentMember = prop.DeclaringType, Value = prop.GetValue(graph)};
                                nodeSchedule.Add(++index, node);
                                
                            }
                            else if (prop.PropertyType.IsInterface || prop.PropertyType.IsClass)
                            {
                                parseGraph(prop.GetValue(graph));
                            }
                        }
                        else if (item is PropertyInfo)
                        {
                            
                            prop = item as PropertyInfo;
                            if ((prop.PropertyType.IsValueType || prop.PropertyType.Equals(typeof(string))))
                            {
                                
                                node = new Node { CurrentMember = prop, ParentMember = prop.DeclaringType, Value = prop.GetValue(graph)};
                                nodeSchedule.Add(++index,node);
                            }
                            else if (prop.PropertyType.IsInterface || prop.PropertyType.IsClass)
                            {
                                parseGraph(prop.GetValue(graph));
                            }
                        }   
                    }
                }//Cursor here 
            }
        }//End of parse method

#endif



    }//Class
}//Namesapce
               
             
          
